from setuptools.command.bdist_egg import analyze_egg

from models.analyzer import Analyzer
from read_grammar import ReadGrammar
from models.grammar import Grammar
from models.production import Production

read_grammar= ReadGrammar('Grammar/grammar1.txt')
grammar = read_grammar.read()
analyzer=Analyzer(grammar)
analyzer.print_states()
analyzer.print_transitions_table()
analyzer.parse_string('bccd')

import tkinter as tk
from tkinter import ttk
import pandas as pd

# 创建主窗口
root = tk.Tk()
root.title("字符串输入和表格展示")
root.geometry("1500x600")

#创建面板
frame_north = ttk.Frame(root, padding=10)
frame_south = ttk.Frame(root, padding=10)
frame_center = ttk.Frame(root, padding=10)
frame1 = ttk.Frame(frame_center, padding=10)
frame2 = ttk.Frame(frame_center, padding=10)
frame3 = ttk.Frame(frame_center, padding=10)

# 使用 Grid 布局来排列 Frame
frame_north.grid(row=0, column=0, sticky="ew")
frame_south.grid(row=2, column=0, sticky="ew")
frame_center.grid(row=1, column=0, sticky="nsew")
# 创建用于固定宽度的填充标签
pad_1 = ttk.Label(frame_center, width=30)
pad_2 = ttk.Label(frame_center, width=70)
pad_3 = ttk.Label(frame_center, width=110)
# 将填充标签放置到网格中
pad_1.grid(row=0, column=0)
pad_2.grid(row=0, column=1)
pad_3.grid(row=0, column=2)
# 然后将框架放置到填充标签下方
frame1.grid(row=1, column=0, sticky="nsew")
frame2.grid(row=1, column=1, sticky="nsew")
frame3.grid(row=1, column=2, sticky="nsew")



# 在每个 Frame 中添加内容
label_north = ttk.Label(frame_north, text="请输入字符串")
label_north.pack()
entry_north = ttk.Entry(frame_north)
entry_north.pack()

text_area1 = tk.Text(frame1, width=30,height=30)
text_area1.pack(expand=True, fill="both")
text_area2 = tk.Text(frame2, width=60,height=30)
text_area2.pack(expand=True, fill="both")
text_area3 = tk.Text(frame3, width=60,height=30)
text_area3.pack(expand=True, fill="both")


inner_frame = ttk.Frame(frame_south)
inner_frame.pack(expand=True)  # 使内部框架扩展以填满南区
button1 = ttk.Button(inner_frame, text="显示文法以及项目集规范族")
button2 = ttk.Button(inner_frame, text="显示状态转移表")
button3 = ttk.Button(inner_frame, text="显示分析栈")
button1.pack(side="left", padx=(10, 0), pady=5)  # 左侧添加一些填充
button2.pack(side="left", padx=5, pady=5)        # 中间按钮不需要额外的填充
button3.pack(side="left", padx=(0, 10), pady=5)  # 右侧添加一些填充

# 使内部框架的按钮居中

inner_frame.pack_configure(padx=10, pady=10)


# 使中心区域在窗口大小变化时能够扩展
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(1, weight=1)




def on_button1_click():
    i=0
    for production in grammar.P:
        text_area1.insert(tk.END, f"[{i}]{production}\n")
        i+=1
    i=0
    for state in analyzer.states:
        text_area1.insert(tk.END, f"I{i}:{state}\n")
        i+=1

button1.config(command=on_button1_click)
def on_button2_click():
    for row in range(len(analyzer.states) + 1):
        for col in range(len(analyzer.all_symbols) + 2):
            text_area2.insert(tk.END,f"{analyzer.transitions_table[row][col]:<5}|")
        text_area2.insert(tk.END, "\n")

button2.config(command=on_button2_click)


def on_button3_click():
    #获取从界面输入的字符串
    input_string=entry_north.get()
    # 将输入字符串添加结束符'#'
    input_string += '#'

    # 初始化分析栈，初始状态，和输入字符串索引
    states_stack = [0]  # 状态栈
    symbol_stack = ['#']  # 符号栈
    input_index = 0  # 相当于是输入串的栈顶指针

    step = 1  # 步骤计数
    goto_state = ''  # 初始化goto_state
    # 打印表头
    text_area3.insert(tk.END,f"步骤 |        状态栈         |             符号栈              |      输入串      | ACTION | GOTO \n")
    while True:

        # 获取当前状态和输入符号
        current_state = states_stack[-1]
        current_symbol = input_string[input_index]

        # 查找LR(0)分析表中的动作
        action = analyzer.get_action(current_state, current_symbol)

        # 打印步骤信息
        text_area3.insert(tk.END,f"{step:<4} |  {str(states_stack):<20} |  {str(symbol_stack):<30} | "
              f" {input_string[input_index:]:<15} | "
              f" {action:<5} | ")

        # 如果动作为空，说明分析表中无对应的动作，字符串不属于文法
        if not action:
            text_area3.insert(tk.END, "\n错误：字符串不属于文法")
            return False

        # 根据动作类型进行处理
        if action.startswith('S'):
            # 移入动作
            next_state = int(action[1:])
            states_stack.append(next_state)
            symbol_stack += input_string[input_index]
            input_index += 1
            text_area3.insert(tk.END, "\n")

        elif action.startswith('r'):
            # 规约动作
            production_index = int(action[1:])
            production = analyzer.grammar.P[production_index]

            # 弹出产生式右部的符号
            for _ in range(len(production.right)):
                states_stack.pop()
                symbol_stack.pop()

            # 获取规约后的状态

            # #查找弹出产生式右部后的符号栈栈顶和产生式左部在状态转移表中对应的动作
            goto_state = analyzer.get_action(states_stack[-1], production.left)
            # 把goto栈的动作移入状态栈
            states_stack.append(goto_state)
            # 把产生式左部移入符号栈
            symbol_stack.append(production.left)

            text_area3.insert(tk.END,f" {goto_state}\n")

        elif action == 'acc':

            print()
            text_area3.insert(tk.END,"接受")
            # 接受动作，字符串属于文法
            return True

        step += 1  # 步骤计数加一

button3.config(command=on_button3_click)
# 运行主循环
root.mainloop()